#pragma once
//日志器模块
//1 抽象出父类,内部将日志消息创建
//子类日志器负责发布
#pragma once
#include"util.hpp"
#include"format.hpp"
#include"sink.hpp"
#include"levels.hpp"
#include"levels.hpp"
#include<vector>
#include<mutex>
#include<atomic>
#include <stdarg.h>
#include"looper.hpp"
#include"buffer.hpp"
#include<memory>
#include<functional>
#include<map>
namespace logs
{
    // Formater::ptr _formater;
    //     std::string _logger;//日志器名称
    //     loglevel::level _limit_level;
    //     std::vector<sink::ptr> _sinks;//保存了该日志器的落地方向
    class Logger
    {
    public:
        using ptr = std::shared_ptr<Logger>;
        Logger(std::string logger,std::vector<sink::ptr> sinks , loglevel::level lev,Formater::ptr& formater)
        :_logger(logger)
        ,_limit_level(lev)
        ,_sinks(sinks)
        ,_formater(formater)
        {
            ;
        }
        // 外部传入文件名,行号,消息主体和格式,让我们内部构建对应级别的日志消息
        void Debug(const std::string& file,size_t line,const char* format,...)
        {
            if(_limit_level > loglevel::level::DEBUG)
                return;
            //制作消息
            va_list vp;
            va_start(vp,format);
            char* ret;
            vasprintf(&ret,format,vp);
            serialize(loglevel::level::DEBUG,file,ret,line);
            free(ret);
            va_end(vp);
        }
         void Info(const std::string& file,size_t line,const char* format,...)
        {
            if(_limit_level > loglevel::level::INFO)
                return;
            //制作消息
            va_list vp;
            va_start(vp,format);
            char* ret;
            vasprintf(&ret,format,vp);
            serialize(loglevel::level::INFO,file,ret,line);
            free(ret);
            va_end(vp);
        }
         void War(const std::string& file,size_t line,const char* format,...)
        {
            if(_limit_level > loglevel::level::WARN)
                return;
            //制作消息
            va_list vp;
            va_start(vp,format);
            char* ret;
            vasprintf(&ret,format,vp);
            serialize(loglevel::level::WARN,file,ret,line);
            free(ret);
            va_end(vp);
        }
         void Fatal(const std::string& file,size_t line,const char* format,...)
        {
            if(_limit_level > loglevel::level::FATAL)
                return;
            //制作消息
            va_list vp;
            va_start(vp,format);
            char* ret;
            vasprintf(&ret,format,vp);
            serialize(loglevel::level::FATAL,file,ret,line);
            free(ret);
            va_end(vp);
        }
         void Error(const std::string& file,size_t line,const char* format,...)
        {
            if(_limit_level > loglevel::level::ERROR)
                return;
            //制作消息
            va_list vp;
            va_start(vp,format);
            char* ret;
            vasprintf(&ret,format,vp);
            serialize(loglevel::level::ERROR,file,ret,line);
            free(ret);
            va_end(vp);
        }
         void Off(const std::string& file,size_t line,const char* format,...)
        {
            if(_limit_level > loglevel::level::OFF)
                return;
            //制作消息
            va_list vp;
            va_start(vp,format);
            char* ret;
            vasprintf(&ret,format,vp);
            serialize(loglevel::level::OFF,file,ret,line);
            free(ret);
            va_end(vp);
        }
        const std::string& name()
        {
            return _logger;
        }
        void serialize(loglevel::level level,const std::string& file,char* cmsg,size_t line)
        {
            LogMsg msg(level,file,_logger,cmsg,line);
            std::string retstring = _formater->format(msg);
            //进行落地
            log(retstring.c_str(),retstring.size());
        }
    protected:
        std::mutex _mutex;
        virtual void log(const char* dst,size_t size) = 0;
        Formater::ptr _formater;
        std::string _logger;//日志器名称
        std::atomic<loglevel::level> _limit_level;
        std::vector<sink::ptr> _sinks;//保存了该日志器的落地方向
    };
    class sync_Logger:public Logger
    {
    public:
        sync_Logger(std::string& logger,std::vector<sink::ptr> sinks,loglevel::level lev,Formater::ptr& formater)
        :Logger(logger,sinks,lev,formater)
        {
            ;
        }
        void log(const char* dst,size_t size)
        {
            std::unique_lock<std::mutex>(_mutex);
            if(_sinks.size() == 0)
                return;
            for(auto e : _sinks)//在写入时要加锁保存
            {
                e->log(dst,size);
            }
        }
    };
     class Async_Logger:public Logger
    {
    public:
        Async_Logger(std::string& logger,std::vector<sink::ptr> sinks,loglevel::level lev,Formater::ptr& formater,loopersafe loopsafe)
        :Logger(logger,sinks,lev,formater)
        ,_looper(std::make_shared<Asynclooper>
            (std::bind(&Async_Logger::realog,this,std::placeholders::_1),loopsafe))
        {
            ;
        }
        void log(const char* dst,size_t size)
        {
            _looper->push(dst,size);//放入缓冲区
        }
        void realog(buffer& buf)//实际落地函数,是传给工作器执行的,会将缓冲区数据给sink落地类函数去落地
        {
            if(_sinks.empty())
                return;
            for(auto e : _sinks)
            {
                e->log(buf.begin(),buf.ReadAbleSize());
            }
        }
    private:
        Asynclooper::ptr _looper;
    };
    enum class LoggerType
    {
        Asynclooper,
        sync_Logger
    };
    //日志器建造者类
    class loggerbuild
    {
    public:
        loggerbuild()
        :_limit_level(loglevel::level::DEBUG)
        ,_type(LoggerType::sync_Logger)
        ,_looper_type(loopersafe::ASYNC_SAFE)
        {
            ;
        }
        void buildlevel(loglevel::level lev)
        {
            _limit_level = lev;
        }
        void buildUnsafeAsync()
        {
            _looper_type = loopersafe::ASYNC_UNSAFE;
        }
        void buildlogname(const std::string& name)
        {
            _logger = name;
        }
        void buildformater(const std::string& parttern)
        {
            _formater  = std::make_shared<Formater>(parttern);
        } 
        void buildloggertype(LoggerType type)
        {
            _type = type;
        }
        template<typename T,typename ...Args>
        void buildsink(Args&& ...args)
        {
           _sinks.push_back(std::make_shared<T>(std::forward<Args>(args)...));
        }
        virtual Logger::ptr  build() = 0;
    protected:
        loopersafe _looper_type;
        std::mutex _mutex;
        LoggerType _type;
        Formater::ptr _formater;
        std::string _logger;//日志器名称
        std::atomic<loglevel::level> _limit_level;
        std::vector<sink::ptr> _sinks;//保存了该日志器的落地方向
    };
    //局部日志器创建
    class Localloggerbuild:public loggerbuild
    {
    public:
        Logger::ptr build()override
        {
            assert(!_logger.empty());
            if(_sinks.empty())
                buildsink<Stdoutsink>();
            if(_formater.get() == nullptr)
                _formater = std::make_shared<Formater>();
            if(_type == LoggerType::Asynclooper)
                return std::make_shared<Async_Logger>(_logger,_sinks,_limit_level,_formater,_looper_type);
            return std::make_shared<sync_Logger>(_logger,_sinks,_limit_level,_formater);
        }
    };
   
    //管理日志模块
    class LoggerManager
    {
    public:
        using ptr = std::shared_ptr<LoggerManager>;
        static LoggerManager& getinstance()//返回单例的管理者对象
        {
            static LoggerManager lm;
            return lm;
        }
        void addlogger(Logger::ptr ptr)//添加一个日志器被管理
        {
            std::unique_lock<std::mutex>(_mutex);
            if(haslogger(ptr->name()))//免得覆盖了
                return;
            _mp.insert(std::make_pair(ptr->name(),ptr));//添加被管理的日志器
        }
        Logger::ptr getlogger(const std::string& name)
        {
            std::unique_lock<std::mutex>(_mutex);//防止别人在别人添加的时候获取,导致获取错误数据
            return _mp[name];
        }
        bool haslogger(const std::string& name)
        {
            std::unique_lock<std::mutex>(_mutex);
            if(_mp.count(name))
                return true;
            return false;    
        }
    private:
        LoggerManager()
        {
            std::unique_ptr<Localloggerbuild> build(new Localloggerbuild());
            build->buildlogname("root");
            //_root日志器只需要指定名称,其余的都有默认的初始化值,默认是安全的不扩容,限制等级为Debug,且为同步日志器
            _root = build->build(); 
            _mp[_root->name()] = _root;
        }
        std::mutex _mutex;
        std::map<std::string,Logger::ptr> _mp;//根据日志器名字返回日志器对象
        Logger::ptr _root;//默认的日志器
    };
     //全局日志器创建
    class Globalloggerbuild:public loggerbuild
    {
    public:
        Logger::ptr build()override
        {
            assert(!_logger.empty());
            if(_sinks.empty())
                buildsink<Stdoutsink>();
            if(_formater.get() == nullptr)
                _formater = std::make_shared<Formater>();
            Logger::ptr logger;
            if(_type == LoggerType::Asynclooper)
                logger =  std::make_shared<Async_Logger>(_logger,_sinks,_limit_level,_formater,_looper_type);
            else
                logger = std::make_shared<sync_Logger>(_logger,_sinks,_limit_level,_formater);
            LoggerManager::getinstance().addlogger(logger);
            return logger;
        }
    };
};
